#!/usr/bin/python
# -*- coding: utf-8 -*-
# @version        : 1.0
# @Create Time    : 2022/3/21 11:03 
# @File           : event.py
# @IDE            : PyCharm
# @desc           : 全局事件

import os
from fastapi import FastAPI
from motor.motor_asyncio import AsyncIOMotorClient
from application.settings import MONGO_DB_URL, EVENTS, CONFIG
from contextlib import asynccontextmanager
from utils.tools import import_modules_async
from core.api_client import ApiConfig
from core.scheduler import Scheduler
from tasks.dispatch import dispatch_task
import atexit

lock_file = '/tmp/scheduler.lock'

def create_lock_file():
    if not os.path.exists(lock_file):
        with open(lock_file, 'w') as f:
            pass
        return True
    return False

@atexit.register
def remove_lock_file():
    if os.path.exists(lock_file):
        os.remove(lock_file)

@asynccontextmanager
async def lifespan(app: FastAPI):

    await import_modules_async(EVENTS, "全局事件", app=app, status=True)

    yield

    await import_modules_async(EVENTS, "全局事件", app=app, status=False)


async def connect_mongo(app: FastAPI, status: bool):
    """
    把 mongo 挂载到 app 对象上面

    博客：https://www.cnblogs.com/aduner/p/13532504.html
    mongodb 官网：https://www.mongodb.com/docs/drivers/motor/
    motor 文档：https://motor.readthedocs.io/en/stable/
    :param app:
    :param status:
    :return:
    """
    if status:
        client: AsyncIOMotorClient = AsyncIOMotorClient(
            MONGO_DB_URL,
            maxPoolSize=10,
            minPoolSize=10,
            serverSelectionTimeoutMS=5000
        )
        app.state.mongo_client = client
        app.state.mongo = client[MONGO_DB_URL.split("=")[-1]]
        # 尝试连接并捕获可能的超时异常
        try:
            # 触发一次服务器通信来确认连接
            data = await client.server_info()
            print("MongoDB 连接成功")
        except Exception as e:
            raise ValueError(f"MongoDB 连接失败: {e}")
    else:
        print("MongoDB 连接关闭")
        app.state.mongo_client.close()


async def check_config(app: FastAPI, status: bool):
    """
    检查配置文件
    """
    def do_check(prefix, config):
        for key, value in config.items():
            key = f"{prefix}.{key}"
            if key.endswith("TRIGGER"):
                try:
                    print(f"检查API配置：{key}")
                    ApiConfig.model_validate(value)
                except Exception as e:
                    raise ValueError(f"配置文件 { key } 检查未通过: {e}")
            elif isinstance(value, dict):
                do_check(key, value)

    if status:
        do_check('CONFIG', CONFIG._wrapped.as_dict())
        print("配置文件 检查通过")
    else:
        pass


async def mount_schedule_task(app: FastAPI, status: bool):
    """
    挂载定时任务
    """
    if status and create_lock_file():
        app.state.scheduler = Scheduler()
        try:
            app.state.scheduler.start()
            app.state.scheduler.add_interval_job(dispatch_task, '10 * * * *')
            print("定时任务启动成功")
        except Exception as e:
            raise ValueError(f"定时任务启动失败: {e}")
    else:
        if getattr(app.state, 'scheduler'):
            print("定时任务关闭")
            app.state.scheduler.shutdown()
        
        remove_lock_file()
        
